//
//  DesSecureHelper.swift
//  cangchu
//
//  Created by kang on 2022/1/25.
//

import Foundation
import CommonCrypto

public class DesSecureHelper:SecureProtocol{
    
    private var key:String?
    private var algorithm = AlgorithmEnum.DES
    
    public init(_ key:String){
        self.key = key
    }
    
    public override func encrypt(param: String) -> String {
        return crypt(operation: CCOperation(kCCEncrypt), key: self.key!, content: param)!
    }
    
    
    public override func deEncrypt(param: String) -> String {
        return crypt(operation: CCOperation(kCCDecrypt), key: self.key!, content: param)!
    }
    
    public override func getAlgorithm() -> AlgorithmEnum {
        return algorithm
    }
    
    public override func getKey() -> String {
        return self.key!
    }
    
    private func crypt(operation:CCOperation, key: String, content:String) -> String? {
           
           if let keyData = key.data(using: .utf8) {
               
               var cryptData: Data?
               
               if operation == kCCEncrypt {
                   cryptData = content.data(using: .utf8)
               } else {
                   cryptData = Data(base64Encoded: content, options: .ignoreUnknownCharacters)
               }
               
               if cryptData == nil {
                   return nil
               }
               
               let algoritm: CCAlgorithm = CCAlgorithm(kCCAlgorithmDES)
               let option: CCOptions = CCOptions(kCCOptionPKCS7Padding)
               
               let keyBytes = [UInt8](keyData)
               let keyLength = kCCKeySizeDES
               
               let dataIn = [UInt8](cryptData!)
               let dataInlength = cryptData!.count
               
               let dataOutAvailable = Int(dataInlength + kCCBlockSizeDES)
               let dataOut = UnsafeMutablePointer<UInt8>.allocate(capacity: dataOutAvailable)
               let dataOutMoved = UnsafeMutablePointer<Int>.allocate(capacity: 1)
               
               dataOutMoved.initialize(to: 0)
               
               let cryptStatus = CCCrypt(operation, algoritm, option, keyBytes, keyLength, keyBytes, dataIn, dataInlength, dataOut, dataOutAvailable, dataOutMoved)
               
               var data: Data?
               
               if CCStatus(cryptStatus) == CCStatus(kCCSuccess) {
                   data = Data(bytesNoCopy: dataOut, count: dataOutMoved.pointee, deallocator: .none)
               }
               
               dataOutMoved.deallocate()
               dataOut.deallocate()
               
               if data == nil {
                   return nil
               }
               
               if operation == kCCEncrypt {
                   data = data!.base64EncodedData(options: .lineLength64Characters)
               }
               
               return String(data: data!, encoding: .utf8)
           }
           
           return nil

       }
}
